package cn.suimg.neo4j;

import cn.suimg.neo4j.dto.DownloadFile;
import cn.suimg.neo4j.util.HttpClientUtil;
import cn.suimg.neo4j.util.ThreadPoolUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

@Slf4j
public class Downloader {

    private static String DOWNLOAD_BASIC_DIR = "F:/KGDownload/";

    public static void startDownloadFileList(List<DownloadFile> downloadFileList){

        Consumer<String> downloadSpeedCallback = speed -> log.info("download speed:{}",speed);
        Consumer<Double> downloadProgressCallback = progress -> log.info("download progress:{}%",progress * 100);

        downloadFileList.forEach(downloadFile -> {
            try {
                downloadFile(downloadFile.getSourceUrl(),new File(DOWNLOAD_BASIC_DIR + downloadFile.getDirName()),downloadFile.getFileName(),downloadSpeedCallback,downloadProgressCallback);
            } catch (IOException e) {
               log.error("download file error",e);
            }
        });
    }

    /**
     * 下载文件到本地方法
     * @param source 下载源链接
     * @param saveDir 保存文件夹
     * @param fileName 保存文件名
     * @param downloadSpeedCallback 下载速度回调
     * @param downloadProgressCallback 下载进度回调
     * @throws IOException
     */
    public static void downloadFile(String source, File saveDir,String fileName,Consumer<String> downloadSpeedCallback, Consumer<Double> downloadProgressCallback) throws IOException {

        HttpClientUtil httpClient = new HttpClientUtil(source).exec();
        //读取响应头的文件大小
        double contentLength = Double.parseDouble(httpClient.getResponseHeader("content-length"));

        if(!saveDir.exists())
            saveDir.mkdirs();

        try(InputStream downloadStream = httpClient.getResponseStream();
            OutputStream outputStream = new FileOutputStream(new File(saveDir,fileName));){
            byte[] cache = new byte[1024 * 8];
            int readLength;
            //是否下载结束
            AtomicBoolean isEnded = new AtomicBoolean(false);
            //总共下载的大小
            AtomicLong totalReadLength = new AtomicLong(0L);

            if (downloadStream != null) {
                //上次下载的大小  可以计算出这一秒下载的大小和上一秒下载的大小 从而计算出下载速度
                AtomicLong lastLength = new AtomicLong(0L);

                //创建一个监听下载速度和下载进度的线程
                ThreadPoolUtil.submit(() -> {
                    while (!isEnded.get()){
                        try {
                            //当前下载下载速度 = 这次总下载长度 - 上次总下载长度
                            //当前下载进度 = 这次下载长度 / 文件总长度
                            long currentDownloadLength = totalReadLength.get();
                            downloadSpeedCallback.accept(String.format("%.2fMB/s",((double) currentDownloadLength  - (double) lastLength.get()) / 1024 / 1024));
                            downloadProgressCallback.accept(Double.valueOf(String.format("%.2f",(double) currentDownloadLength / contentLength)));
                            lastLength.set(currentDownloadLength);
                            Thread.sleep(1000);
                        } catch (InterruptedException ignored) { }
                    }
                });

                while ((readLength = downloadStream.read(cache)) != -1) {
                    outputStream.write(cache, 0, readLength);
                    totalReadLength.getAndAdd(readLength);
                }
                isEnded.set(true);
                downloadSpeedCallback.accept("下载完成");
                downloadProgressCallback.accept(1D);
            }
        }
    }
}
